#include <crt_util.h>

int is_big_little(void)
{
    int val = 0x04030201;
    char firstByte = *(char*)&val;

    if (firstByte == 0x01) {
        return little_endian;
    } else if (firstByte == 0x04) {
        return big_endian;
    }
    return null_endian;
}

uint16_t blushort(uint16_t value)
{
    return ((value & 0x00FF) << 8) | ((value & 0xFF00) >> 8);
}

uint32_t bluint32(uint32_t value)
{
    return ((value & 0x000000FF) << 24) | ((value & 0x0000FF00) << 8) | ((value & 0x00FF0000) >> 8) | ((value & 0xFF000000) >> 24);
}

int uint64touint32(uint64_t u64value, uint32* u32value)
{
    rc_error(u32value != NULL, S_ERROR) uint8_t u8value[8] = {0x00};
    un_putll(u8value, u64value);

    int rc = 0;

    if (is_big_little() == little_endian) {
        rc = u8value[0] == 0x00 && u8value[1] == 0x00 && u8value[2] == 0x00 && u8value[3] == 0x00;
        rc_error(rc > 0, S_ERROR);

        uint32_t value;
        value = (((uint32_t)u8value[4]) << 24) | (((uint32_t)u8value[5]) << 16) | (((uint32_t)u8value[6]) << 8) | ((uint32_t)u8value[7]);

        *u32value = value & UINT32_MAX;
    } else if (is_big_little() == big_endian) {
        rc = u8value[4] == 0x00 && u8value[5] == 0x00 && u8value[6] == 0x00 && u8value[7] == 0x00;
        rc_error(rc > 0, S_ERROR);

        uint32_t value;
        value = (((uint32_t)u8value[0]) << 24) | (((uint32_t)u8value[1]) << 16) | (((uint32_t)u8value[2]) << 8) | ((uint32_t)u8value[3]);

        *u32value = value & UINT32_MAX;
    }

    return S_ERROR;
}

uint16_t un_gets(const uint8_t* buf)
{
    return (((uint16_t)buf[0]) << 8) | ((uint16_t)buf[1]);
}

void un_puts(uint8_t* buf, uint16_t val)
{
    buf[0] = (uint8_t)(((val) >> 8) & 0xff);
    buf[1] = (uint8_t)(val & 0xff);
}

uint32_t un_getl(const uint8_t* buf)
{
    return (((uint32_t)buf[0]) << 24) | (((uint32_t)buf[1]) << 16) | (((uint32_t)buf[2]) << 8) | ((uint32_t)buf[3]);
}

void un_putl(uint8_t* buf, uint32_t val)
{
    buf[0] = (uint8_t)(((val) >> 24) & 0xff);
    buf[1] = (uint8_t)(((val) >> 16) & 0xff);
    buf[2] = (uint8_t)(((val) >> 8) & 0xff);
    buf[3] = (uint8_t)(val & 0xff);
}

uint64_t un_getll(const uint8_t* buf)
{
    return (((uint64_t)buf[0]) << 56) | (((uint64_t)buf[1]) << 48) | (((uint64_t)buf[2]) << 40) | (((uint64_t)buf[3]) << 32)
           | (((uint64_t)buf[4]) << 24) | (((uint64_t)buf[5]) << 16) | (((uint64_t)buf[6]) << 8) | (((uint64_t)buf[7] << 0));
}

void un_putll(uint8_t* buf, uint64_t val)
{
    buf[0] = (uint8_t)((val >> 56) & 0xff);
    buf[1] = (uint8_t)((val >> 48) & 0xff);
    buf[2] = (uint8_t)((val >> 40) & 0xff);
    buf[3] = (uint8_t)((val >> 32) & 0xff);
    buf[4] = (uint8_t)((val >> 24) & 0xff);
    buf[5] = (uint8_t)((val >> 16) & 0xff);
    buf[6] = (uint8_t)((val >> 8) & 0xff);
    buf[7] = (uint8_t)(val & 0xff);
}
